﻿using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using X = Adjunct.Framework.Nuspec.XNames.Package.Metadata.FrameworkAssemblies;

namespace Adjunct.Framework.Nuspec
{
	/// <summary>
	/// 
	/// </summary>
	/// <remarks></remarks>
	public class NuspecFrameworkReferences : List<NuspecFrameworkReference>
	{
		/// <summary>
		/// Adds the specified assembly name.
		/// </summary>
		/// <param name="assemblyName">Name of the assembly.</param>
		/// <param name="targetFramework">The target framework.</param>
		/// <remarks></remarks>
		public void Add(string assemblyName, string targetFramework = null)
		{
			Add(new NuspecFrameworkReference(assemblyName, targetFramework));
		}

		/// <summary>
		/// Clones this instance.
		/// </summary>
		/// <returns></returns>
		/// <remarks></remarks>
		public NuspecFrameworkReferences Clone()
		{
			NuspecFrameworkReferences clone = new NuspecFrameworkReferences();
			clone.AddRange(this.Select(reference => reference.Clone()));
			return clone;
		}

		/// <summary>
		/// Performs an explicit conversion from <see cref="Adjunct.Framework.Nuspec.NuspecFrameworkReferences"/> to
		/// <see cref="System.Xml.Linq.XElement"/>.
		/// </summary>
		/// <param name="frameworkReferences">The framework references.</param>
		/// <returns>Returns null if the references are null or empty for sparse xml.</returns>
		/// <remarks></remarks>
		public static explicit operator XElement(NuspecFrameworkReferences frameworkReferences)
		{
			if ((frameworkReferences == null) || (frameworkReferences.Count == 0))
			{
				return null;
			}
			return new XElement(X.ElementName, frameworkReferences.OrderBy(r => r.AssemblyName).Select(r => (XElement)r));
		}

		/// <summary>
		/// Performs an explicit conversion from <see cref="System.Xml.Linq.XElement"/> to
		/// <see cref="Adjunct.Framework.Nuspec.NuspecFrameworkReferences"/>.
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>Always returns an instance so that the consumer doesn't have to see if one was created.</returns>
		/// <remarks></remarks>
		public static explicit operator NuspecFrameworkReferences(XElement element)
		{
			NuspecFrameworkReferences references = new NuspecFrameworkReferences();
			if (element != null)
			{
				element.EnsureElementNameIs(X.ElementName);
				references.AddRange(element.Elements(X.FrameworkAssembly.ElementName).Select(child => (NuspecFrameworkReference)child));
			}
			return references;
		}
	}
}